/**
 * 思路:通过简单的 el-table的 thead和tbody父级别区域，进行设置对于的fixed
 * 1.复制一份 thead 设置为fixed,先隐藏掉。
 * 2.创建滚动条监听事件，根据滚动条计算表格所在可视窗口位置。设置thead副本是否显示
 * 3.创建横向滚动条的属性变化监听。当监听变化时，说明在拖动横向滚动条，需要将设置对应副本的表头位置，防止错位
 */

const Z_INDEX = 1994;

function getElParentBySelector(el: any, queryClassSelector: string) {
  if (!el) {
    return el;
  }
  if ([...el.classList].includes(queryClassSelector)) {
    return el;
  }
  return getElParentBySelector(el.parentNode, queryClassSelector)
}

function getTableShowWidth(thead: string) {
  const tableBox = getElParentBySelector(thead, 'el-table');
  return tableBox.getBoundingClientRect().width;
}

//使用setTime来确保不会重复设置

function createTableSticky(el: any, binding: any, vNode?: any) {

  // 获取滚动元素
  const scrollParent = binding.value?.parentId ? document.getElementById(binding.value.parentId) : document.querySelector('#app-main');

  let stickyTop = scrollParent.getBoundingClientRect().top;

  stickyTop = parseFloat(stickyTop);

  // 获取表格(element)
  let thead = el.querySelector('.el-table__header');

  thead = getElParentBySelector(thead, 'el-table__header-wrapper');

  const tbody = el.querySelector('.el-table__body-wrapper') || el.querySelector('.el-table__body');

  tbody.classList.add('sticky-table');

  const elBodyBox = el.querySelector('.el-table__body-wrapper');

  const scrollbarBar = el.querySelector('.el-table__body-wrapper .el-scrollbar .el-scrollbar__bar.is-horizontal');

  /**
   * 插入副本元素，确保文档流不塌陷
   */
  const copyThead = thead.cloneNode(true);

  copyThead.classList.add('el-table_header-copy');
  copyThead.style.display = 'none';

  thead.parentNode.insertBefore(copyThead, elBodyBox);

  //获取thead 的显示宽度
  let headerShowWidth = getTableShowWidth(thead);

  if (!scrollParent) {
    return;
  }

  scrollParent.addEventListener('scroll', () => {
    setScrollbarThumb();
    setTheadFixed();
  })

  /** 设置表头吸顶 */
  function setTheadFixed() {
    const theadHeight = thead.clientHeight;

    // 获取thead距离顶部的距离
    const theadTop = thead.getBoundingClientRect().top;

    // 判断是否需要回归原来位置
    const originally = tbody.getBoundingClientRect().top;

    // 判断底部距离是否超过表头
    const goBeyond = tbody.getBoundingClientRect().bottom;

    if (theadTop <= stickyTop) {
      copyThead.style.display = 'block'

      // 设置表头 fixed 定位
      const theadWidth = (headerShowWidth != 0 && headerShowWidth < tbody.offsetWidth) ? headerShowWidth :  tbody.offsetWidth;
      thead.style.width = theadWidth ? theadWidth + 'px' : '';
      thead.style.borderBottom = '1px solid #e0e0e0';
      thead.style.position = 'fixed';
      thead.style.top = stickyTop + 'px';
      thead.style.zIndex = Z_INDEX;
    }

    if (originally - theadHeight > stickyTop || goBeyond - theadHeight / 2 <= stickyTop) {
      //影藏副本
      copyThead.style.display = 'none';

      // 表头归位
      thead.style.width = '';
      thead.style.borderBottom = ''
      thead.style.position = '';
      thead.style.top = '';
      thead.style.zIndex = '';
    }
  }

  try {
    //启动底部滚动条监控，防止横向滚动条滚动，表头没有动的问题
    const elThumbBut = el.querySelector('.el-table__body-wrapper .el-scrollbar .el-scrollbar__bar.is-horizontal .el-scrollbar__thumb');

    if (elThumbBut) {
      const observer = new MutationObserver(mutationsList => {
        for (const mutation of mutationsList) {
          if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
            // CSS样式发生了变化
            // 将 thumb 滚动条的
            const transformX = elThumbBut.style.transform;
            if (transformX) {
              copyThead.querySelector('.el-table__header').style.marginLeft = `-${transformX.replace(/[a-zA-Z()]/g, '')}`;
            }
          }
        }
      })
      //开始监听横向滚动条
      observer.observe(elThumbBut, { attributes: true });
    }
  } catch (error) {}

  setScrollbarThumb();

  /** 设置底部滚动条 吸底 */
  function setScrollbarThumb() {
    headerShowWidth = getTableShowWidth(thead);

    const theadWidth = (headerShowWidth != 0 && headerShowWidth < tbody.offsetWidth) ? headerShowWidth :  tbody.offsetWidth;

    thead.style.width = theadWidth ? theadWidth + 'px' : '';

    // 父元素距离窗口顶部
    let parentBottom = scrollParent.getBoundingClientRect().bottom;

    // 服元素距离底部
    let distanceBottom = document.body.getBoundingClientRect().bottom - parentBottom

    // 表格距离父元素底部
    const tableBottom = el.getBoundingClientRect().bottom - parentBottom;

    // 已设置吸底的分页器元素
    const pageinationDom = el.parentNode?.querySelector('.pagination-container .pagination-fixed');

    const scrollBottem = pageinationDom ? 42 : 5;

    if (tableBottom > -scrollBottem) {
      scrollbarBar.style.position = 'fixed';
      scrollbarBar.style.zIndex = Z_INDEX;
      scrollbarBar.style.bottom = distanceBottom + scrollBottem + 'px';
      scrollbarBar.style.left = el.getBoundingClientRect().left + 'px';

      if (pageinationDom) {
        pageinationDom.style.position = 'fixed';
        pageinationDom.style.backgroundColor = '#fff';
        pageinationDom.style.width = el.getBoundingClientRect().width + 'px';
        pageinationDom.style.zIndex = Z_INDEX;
        pageinationDom.style.bottom = distanceBottom + 'px';
      }
    } else {
      scrollbarBar.style.position = '';
      scrollbarBar.style.zIndex = '';
      scrollbarBar.style.bottom = '';
      scrollbarBar.style.left = '';

      if (pageinationDom) {
        pageinationDom.style.position = '';
        pageinationDom.style.backgroundColor = '';
        pageinationDom.style.width = '';
        pageinationDom.style.zIndex = '';
        pageinationDom.style.bottom = '';
      }
    }
  }

  const resizeObserver = new ResizeObserver(entries => {
    setScrollbarThumb();
  })

  resizeObserver.observe(el);
  resizeObserver.observe(scrollParent);
}

// el-table表头吸顶效果
export default {
  // 当被绑定的元素插入到 DOM 中时……
  mounted(el: any, binding: any) {
    createTableSticky(el, binding);
  },

  update(el: any, binding: any) {
    createTableSticky(el, binding);
  },

}

